const Order = require("../model/order.model");

class OrderService {
  constructor() {
    /**
     * 核心目的：确保 createOrder 方法在任意调用方式下（实例调用/解构后调用），this 都能稳定指向当前 OrderService 实例
     * 执行逻辑拆解：
     *  1. 读取原型方法：构造函数中的 this 指向新创建的实例，通过 this.createOrder 会先从原型（OrderService.prototype）上读取原始的 createOrder 方法（因为此时实例自身还未定义该属性）；
     *  2. 绑定 this 生成新函数：调用 bind(this)，强制将新函数的 this 锁定为当前实例（构造函数中的 this），后续无论如何调用该新函数，this 都不会变更；
     *  3. 实例挂载新函数：将“锁定了 this 的新函数”赋值给实例自身的 createOrder 属性，此时实例会优先使用自身的该属性，而非原型上的原始方法；
     *  4. 解决的问题：避免解构调用时 this 丢失（如 const { createOrder } = orderService; createOrder()），确保能正常访问 this.getUniqueOrderNumber() 等实例方法。
     */
    this.createOrder = this.createOrder.bind(this);
    /**
     * 补充说明：
     * - 若其他方法（如 getUniqueOrderNumber、后续新增的 updateOrder 等）也需要支持“解构后调用”，需按相同逻辑执行绑定；
     * - 绑定逻辑仅需在构造函数中执行一次（实例创建时），后续调用方法无需重复处理。
     */
    // this.getUniqueOrderNumber = this.getUniqueOrderNumber.bind(this); // 示例：其他方法的绑定写法
  }

  /**
   * 生成并获取唯一订单编号（确保数据库中无重复）
   * @param {number} [retryCount=0] 递归重试次数（内部参数，外部调用无需传）
   * @returns {Promise<string>} 19位固定长度的唯一订单编号
   * @throws {Error} 重试次数超过限制时抛出错误
   */
  async getUniqueOrderNumber(retryCount = 0) {
    // 限制最大重试次数（如5次），避免极端情况栈溢出
    if (retryCount >= 5) {
      throw new Error("生成订单编号失败：超过最大重试次数，可能存在异常并发");
    }
    const prefix = "XZD"; // 业务前缀，可根据实际业务调整（如平台简称）
    const timestamp = Date.now().toString(); // 13位毫秒时间戳（字符串形式，避免数字类型溢出）
    // 生成3位随机数，不足3位用0补前导（如23 → "023"，确保长度固定）
    const random = Math.floor(Math.random() * 1000)
      .toString()
      .padStart(3, "0");
    const orderNumber = `${prefix}${timestamp}${random}`; // 最终长度：3 + 13 + 3 = 19位（固定）
    // 兜底校验：查询数据库，若编号已存在则递归重新生成（极端情况容错）
    const isExist = await Order.findOne({
      where: { order_number: orderNumber },
      attributes: ["id"], // 告诉数据库“找到记录后，要返回该记录的哪些字段”。只查询需要的字段，可以减少数据传输，优化性能（不设置时查询所有字段）
    });
    // 若存在，递归重新生成（理论概率极低），重试时次数+1
    return isExist ? this.getUniqueOrderNumber(retryCount + 1) : orderNumber;
  }
  /**
   * 创建订单
   * @param {*} orderInfo 订单信息
   * @returns 创建的订单信息
   */
  async createOrder(orderInfo) {
    // 获取生成的订单编号
    const order_number = await this.getUniqueOrderNumber();
    const order = { ...orderInfo, order_number };
    const res = await Order.create(order);
    return res;
  }
  /**
   * 查询订单列表
   * @param {*} pageNum 查询第几页
   * @param {*} pageSize 页码
   * @param {*} status 订单状态
   * @returns {object} 查询结果
   */
  async findAllOrder(pageNum, pageSize, status) {
    pageNum = pageNum * 1;
    pageSize = pageSize * 1;
    const { count, rows } = await Order.findAndCountAll({
      where: { status },
      attributes: ["goods_info", "total", "order_number", "status"], // 告诉数据库“找到记录后，要返回该记录的哪些字段”。只查询需要的字段，可以减少数据传输，优化性能（不设置时查询所有字段）
      offset: (pageNum - 1) * pageSize,
      limit: pageSize,
    });
    const result = {
      pageNum,
      pageSize,
      total: count,
      list: rows,
    };
    return result;
  }
  /**
   * 根据订单id更新订单状态
   * @param {*} id 订单id
   * @param {*} status 订单状态
   * @returns {boolean} 更新结果
   */
  async updateOrder(id, status) {
    const res = await Order.update(
      { status },
      {
        where: { id },
      },
    );
    return res[0] > 0 ? true : false;
  }
}

module.exports = new OrderService();
